home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 314.adf / Zc / zcsrc.lzh / genstubs / genfunc.c next >
C/C++ Source or Header  |  1989-06-10  |  4KB  |  218 lines

  1. /*
  2.  * Genfunc: Generates the assembler to put the C parameters on the
  3.  * stack to the required registers, and call the RKM procedure.
  4.  *
  5.  * Copyright 1988 by J.A. Lydiatt.  Permission is given to freely
  6.  * distribute and/or modify this code for non-commmercial use.
  7.  * Maintenance Notes:
  8.  *   18Jun88 - V1.0 Created by Jal.
  9.  */
  10.  
  11. #include "genstubs.h"
  12. #define PERMREGS    (~(0x0303))
  13. #define REGA6          (0x4000)
  14.  
  15. typedef struct xdefnode {
  16.     struct xdefnode *next;
  17.     char   name[1];
  18.     } XDEFNODE;
  19.  
  20.  
  21. /*
  22.  * External variables:
  23.  */
  24.  
  25. extern char base[];            /* ##base _SysBase for example    */
  26. extern int  bias;            /* ##bias 30            */
  27. extern char Section[];            /* SECTION "<Section>",CODE    */
  28. extern FUNCINFO function;        /* The current function.    */
  29.  
  30. static XDEFNODE *xdeflist = NULL;
  31. static FILE *fo;
  32.  
  33. /*
  34.  * genfunc: support code to generate the function.
  35.  */
  36.  
  37. static int getrange( mask, frombit, tobit )
  38. register unsigned int mask;
  39. int frombit, tobit;
  40. {
  41.     register int bit;
  42.  
  43.     for (bit=frombit; bit <= tobit; ++bit ){
  44.         if ( !(mask & 1 << bit ))
  45.             break;
  46.     }
  47.  
  48.     return --bit;
  49. }
  50.  
  51. static int makelist( list, mask, frombit, tobit, idchar )
  52. char list[];
  53. register unsigned int mask;
  54. int frombit, tobit;
  55. char idchar;
  56. {
  57.     int bit, endbit, nperm, endrange;
  58.     char tmp[32];
  59.     extern int sprintf();
  60.     extern char *strcat();
  61.  
  62.     nperm = 0;
  63.     for ( bit=frombit; bit <= tobit; ++bit ){
  64.         if ( mask & 1 << bit ){
  65.             endrange = getrange( mask, bit, tobit );
  66.             if ( endrange > bit )
  67.                 (void) sprintf( tmp, "/%c%d-%c%d",
  68.                     idchar, bit % 8,
  69.                     idchar, endrange % 8);
  70.             else
  71.                 (void) sprintf( tmp, "/%c%d",
  72.                     idchar, bit % 8 );
  73.             (void)strcat( list, tmp ); 
  74.             nperm += endrange - bit + 1;
  75.             bit = endrange;
  76.         }
  77.     }
  78.     return nperm;
  79. }
  80.  
  81. static int getperm( mask, list )
  82. unsigned int mask;
  83. char *list;
  84. {
  85.     char tmplist[64];
  86.     int nperm;
  87.     extern char *strcpy();
  88.  
  89.     tmplist[0] = '\0';
  90.     nperm =  makelist( tmplist, mask, 0, 7, 'D' );
  91.     nperm += makelist( tmplist, mask, 8, 15, 'A' );
  92.     if ( tmplist[0] != '\0' )
  93.         strcpy( list, &tmplist[1] );
  94.     else
  95.         list[0] = '\0';
  96.     return nperm;
  97. }
  98.  
  99. static void gencomment( txt )
  100. char *txt;
  101. {
  102.     fprintf( fo, "* %s\n", txt );
  103. }
  104.  
  105. static void gen( code, p1, p2, p3, p4 )
  106. char *code;
  107. long p1, p2, p3, p4;
  108. {
  109.     putc( '\t', fo );
  110.     fprintf( fo, code, p1, p2, p3, p4);
  111.     putc( '\n', fo );
  112. }
  113.  
  114. static void genlabel( label )
  115. char *label;
  116. {
  117.     (void)fputs( label, fo );
  118.     (void)putc( '\n', fo );
  119. }
  120.  
  121. void genfunc()
  122. {
  123.     int  nperm;        /* # Permanent registers used */
  124.     int  permmask;        /* Mask for permanent regs used. */
  125.     int  offset;
  126.     int  j;
  127.     FUNCINFO *f;        /* Pointer to function info struct */ 
  128.     char permlist[128];
  129.     void assemble();
  130.  
  131.     /*
  132.      * print the current line as a comment.
  133.      */
  134.  
  135.     f = &function;
  136.     sprintf( permlist, "ram:%s.a", &f->name[1] );
  137.     if ( (fo = fopen( permlist, "w")) == NULL ) {
  138.         fprintf( stderr, "Can't open: %s\n", permlist );
  139.         exit( 12 );
  140.     }
  141.  
  142.     gencomment("");
  143.     gencomment( f->givenline );
  144.     gencomment( "" );
  145.  
  146.     /*
  147.      * Start a new Section Name.
  148.      */
  149.  
  150.     gen( "SECTION\t%s,CODE", Section );
  151.     gen( "XDEF\t%s", f->name );
  152.     gen( "XREF\t%s", base );
  153.     genlabel( f->name );
  154.  
  155.     /*
  156.      * Save any permanent registers used.
  157.      */
  158.  
  159.     nperm = getperm( f->regmask & PERMREGS | REGA6 , permlist );
  160.     if ( nperm )
  161.         gen( "MOVEM.L\t%s,-(a7)", permlist );
  162.  
  163.     /*
  164.      * Generate a move instruction for each list.
  165.      */
  166.  
  167.     offset = 4 + nperm * 4;
  168.     for ( j=0; j<f->nlists; ++j ) {
  169.         gen( "MOVEM.L\t%d(A7),%s", offset, f->reglist[j] );
  170.         offset += f->nregs[j] * 4;
  171.     }
  172.  
  173.     /*
  174.      * Generate the jump instruction, restore perm and exit.
  175.      */
  176.  
  177.     gen( "MOVEM.L\t%s,A6", base );
  178.     gen( "JSR\t%d(A6)", -bias );
  179.     if ( nperm )
  180.         gen( "MOVEM.L\t%(a7)+,%s", permlist );
  181.     gen( "RTS" );
  182.     gen( "END" );
  183.  
  184.     fclose( fo );
  185.     assemble( &f->name[1] );
  186.  
  187. }
  188.  
  189.  
  190. /*
  191.  * assemble a generated stub.
  192.  */
  193.  
  194. #define ASSEMBLER "a68k"
  195. #define AOPTION   "-d"
  196.  
  197. static void
  198. assemble( stub )
  199. char *stub;
  200. {
  201.     register XDEFNODE *p, *q;
  202.     char tmp1[128];
  203.     char tmp2[128];
  204.     int fexecl();
  205.     void unlink();
  206.  
  207.     sprintf( tmp1, "ram:%s.a", stub);
  208.     sprintf( tmp2, "-oram:%s.o", stub);
  209.  
  210.     printf( "%s %s %s %s\n", ASSEMBLER, AOPTION, tmp1, tmp2); 
  211.     fexecl( ASSEMBLER,
  212.         AOPTION,
  213.         tmp1,
  214.         tmp2,
  215.         NULL);        
  216.     unlink( tmp1 );            
  217. }
  218.